package com.lucy.disk.onlyoffice.provider;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import com.lucy.common.constant.HttpStatus;
import com.lucy.common.exception.BusinessException;
import com.lucy.disk.constant.FileTypeEnum;
import com.lucy.disk.loader.OfficeServiceLoader;
import com.lucy.disk.loader.StorageServiceLoader;
import com.lucy.disk.onlyoffice.constant.DocumentStatus;
import com.lucy.disk.onlyoffice.entity.Document;
import com.lucy.disk.onlyoffice.entity.DocumentEditCallback;
import com.lucy.disk.onlyoffice.entity.DocumentEditCallbackResponse;
import com.lucy.disk.onlyoffice.entity.DocumentEditParam;
import com.lucy.disk.onlyoffice.service.DocumentService;
import com.lucy.disk.utils.DiskUtil;
import com.lucy.rabc.entity.SysUser;
import com.lucy.rabc.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Optional;

/**
 * @author kindear
 * 预览服务提供
 */
@Primary
@Slf4j
@Service
public class OfficeServiceProvider implements OfficeServiceLoader {
    @Autowired
    DocumentService documentService;

    @Autowired
    SysUserService userService;

    @Autowired
    StorageServiceLoader storageService;

    @Override
    public ModelAndView loadPreviewView(String documentKey, HttpServletResponse response) throws IOException {
        Document document = documentService.getDocument(documentKey);
        if (DiskUtil.getFileType(document.getTitle()).equals(FileTypeEnum.DOCUMENT.getDesc())){
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("viewer");
            modelAndView.addObject("document",documentService.getDocument(documentKey));
            return modelAndView;
        }
        // 转发默认预览方法
        response.sendRedirect("/disk/default/preview/"+documentKey);
        return null;
    }

    @Override
    public ModelAndView loadEditorView(String documentKey, HttpServletResponse response) throws IOException {
        if (!StpUtil.isLogin()){
            throw new BusinessException(HttpStatus.UNAUTHORIZED);
        }
        Long loginId = StpUtil.getLoginIdAsLong();
        Optional<SysUser> userOp = userService.getOne(loginId);
        if (!userOp.isPresent()){
            throw new BusinessException(HttpStatus.NOT_FOUND);
        }
        SysUser user = userOp.get();
        String userName = user.getUserName();
        DocumentEditParam documentEditParam = documentService.buildDocumentEditParam(loginId.toString(),userName);
        Document document = documentService.getDocument(documentKey);
        if (documentService.canEdit(document)){
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("editor");
            modelAndView.addObject("document",document);
            modelAndView.addObject("documentEditParam",documentEditParam);
            return modelAndView;
        }else {
            // 不满足编辑条件 返回预览
            response.sendRedirect("/disk/preview/"+documentKey);
            return null;
        }
    }

    @Override
    public Object editorCallBack(Map<String, Object> map) {
        DocumentEditCallback callback = BeanUtil.fillBeanWithMap(map,new DocumentEditCallback(),false);

        if (log.isInfoEnabled()) {
            log.info("### 编辑后回调, 回调信息：{}", callback);
        }
        // 需要保存时写出文件
        if (callback.getStatus() == DocumentStatus.READY_FOR_SAVING.getCode() || callback.getStatus() == DocumentStatus.BEING_EDITED_STATE_SAVED.getCode()) {
            if (log.isDebugEnabled()) {
                log.debug("@@@ 开始保存文件。。。");
            }
            Document document = documentService.getDocument(callback.getKey());
            File saveFile = FileUtil.touch(document.getTitle());
            boolean success = false;
            try {
                FileUtils.copyURLToFile(new URL(callback.getUrl()), saveFile);
                // 存储服务更新
                storageService.updateFile(FileUtil.getInputStream(saveFile), document.getKey());
                if (saveFile.exists() && saveFile.length() > 0) {
                    success = true;
                }
            }catch (Exception e){
                log.error("$$$ 保存文档失败！", e);
            }

            //boolean success = documentService.saveDocumentFile(callback.getKey(), callback.getUrl());
            if (log.isDebugEnabled()) {
                log.debug("@@@ 保存文件结束！");
            }
            if (!success) {
                return DocumentEditCallbackResponse.failue();
            }
        }
        return DocumentEditCallbackResponse.success();
    }
}
